'''
对象的引用时，如何知道这个对象是什么类型、有哪些方法呢
'''

# 首先，我们来判断对象类型，使用type()函数：
# 基本类型都可以用type()判断：

print(type(123123))

#如果一个变量指向函数或者类，也可以用type判断

print(type(abs))
a=9

class Student(object):
    pass

stu=Student()
print(type(stu))

#。如果我们要在if语句中判断，就需要比较两个变量的type类型是否相同

if type('ACA')==str:
    print('is str')
else:
    print('not a  str')

if type(13)==str:
    print('is str')
else:
    print('not a  str')
#判断基本数据类型可以直接写int，str等，但如果要判断一个对象是否是函数怎么办？可以
# 使用types模块中定义的常量：

import types
def fn():
    pass

print(type(fn)==types.FunctionType)
print(type(abs)==types.BuiltinFunctionType)

#使用isinstance()
# 对于class的继承关系来说，使用type()就很不方便。我们要
# 判断class的类型，可以使用isinstance()函数。


#继承，继承父类的方法
class Animal(object):
    def run(self):
        print('Animal is running')


class Dog(Animal):
    pass


class Cat(Animal):
        pass
ani=Animal()
ani.run()

dog=Dog()
dog.run()

cat=Cat()
cat.run()

#当子类和父类都存在相同的run()方法时，我们说，子类的r
# un()覆盖了父类的run()，在代码运行的时候，总是会调用子类的run()。这
# 样，我们就获得了继承的另一个好处：多态。

class Horse(Animal):
    def run(self):
        print("Horse is running")

horse=Horse()
horse.run()

# 判断一个变量是否是某个类型可以用isinstance()判断：总是优先使用isinstance()判断类型，可以将指定类型及其子类“一网打尽”。
print(isinstance(horse,Horse))#子类就是子类
print(isinstance(horse,Animal))#子类也是父类

#并且还可以判断一个变量是否是某些类型中的一种，比如下面的代码就可以判断是否是list或者tuple：

print(isinstance([1, 2, 3], (list, tuple)))

#使用dir要获得一个对象的所有属性和方法，可以使用dir()函数，它返回一个包含字符串的list，比如，获得一个str对象的所有属性和方法：

print(dir('ACV'))
print(len("acd"))
print('acd'.__len__())

#仅把属性和方法列出来是不够的，配合getattr()、setattr()以及hasattr()，我们可以直接操作一个对象的状态：

class MyObject(object):
    def __init__(self):
        self.x=9

    def power(self):
        return self.x*self.x

obj=MyObject()

print(hasattr(obj,"x"))

print(hasattr(obj,"y"))

setattr(obj,'y',19)

print(hasattr(obj,'y'))

print(getattr(obj,'y'))

print(obj.y)

#如果试图获取不存在的属性，会抛出AttributeError的错误：
# print(getattr(obj,'z'))
#可以传入一个default参数，如果属性不存在，就返回默认值：
print(getattr(obj,'z',404))

#也可以获得对象的方法：

print(hasattr(obj,'power'))

fn=getattr(obj,'power')
print(fn())


'''
一个正确的用法的例子如下：

def readImage(fp):
    if hasattr(fp, 'read'):
        return readData(fp)
    return None
假设我们希望从文件流fp中读取图像，我们首先要判断该fp对象是否存在read方法，如果存在，则该对象是一个流，如果不存在，则无法读取。hasattr()就派上了用场。

请注意，在Python这类动态语言中，根据鸭子类型，有read()方法，不代表该fp对象就是一个文件流，它也可能是网络流，也可能是内存中的一个字节流，但只要read()方法返回的是有效的图像数据，就不影响读取图像的功能。



'''
